package com.fjjn.component;

import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RBlockingDeque;
import org.redisson.api.RDelayedQueue;
import org.redisson.api.RedissonClient;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.concurrent.TimeUnit;

@Slf4j
@Component
@ConditionalOnProperty(name = "delay.queue.enable",havingValue = "true")
public class RedissionDelayQueueService {

    private final RedissonClient redissonClient;

    public RedissionDelayQueueService(RedissonClient redissonClient) {
        this.redissonClient = redissonClient;
    }

    /**
     * 添加延迟队列
     *
     * @param value     队列值
     * @param delay     延迟时间
     * @param timeUnit  时间单位
     * @param queueCode 队列键
     * @param <T>
     */
    public <T> void addDelayQueue(@NonNull T value, long delay, @NonNull TimeUnit timeUnit, @NonNull String queueCode) {
        if (!StringUtils.hasText(queueCode)) {
            return;
        }
        try {
            RBlockingDeque<Object> blockingDeque = redissonClient.getBlockingDeque(queueCode);
            RDelayedQueue<Object> delayedQueue = redissonClient.getDelayedQueue(blockingDeque);
            delayedQueue.offer(value, delay, timeUnit);
            log.info("<<<添加延时队列>>> redisKey：{}，队列值：{}，延迟 {} 秒执行", queueCode, value, timeUnit.toSeconds(delay));
        } catch (Exception e) {
            log.error("<<<添加延时队列失败>>> {}", e.getMessage());
            throw new RuntimeException("(添加延时队列失败)");
        }
    }
    /**
     * 获取延迟队列
     *
     * @param queueCode 队列名称对应的代码
     */
    public <T> T getDelayQueue(@NonNull String queueCode) throws InterruptedException {
        if (!StringUtils.hasText(queueCode)) {
            return null;
        }
        RBlockingDeque<T> blockingDeque = redissonClient.getBlockingDeque(queueCode);
        //没用到，但是不能去掉
        RDelayedQueue<T> delayedQueue = redissonClient.getDelayedQueue(blockingDeque);
        return blockingDeque.poll();
    }

    /**
     * 删除指定队列中的消息
     *
     * @param o 指定删除的消息对象队列值(同队列需保证唯一性)
     * @param queueCode 指定队列键
     */
    public boolean removeDelayedQueue(@NonNull Object o, @NonNull String queueCode) {
        if (!StringUtils.hasText(queueCode)) {
            return false;
        }
        RBlockingDeque<Object> blockingDeque = redissonClient.getBlockingDeque(queueCode);
        RDelayedQueue<Object> delayedQueue = redissonClient.getDelayedQueue(blockingDeque);
        return delayedQueue.remove(o);
    }
}
